/*
    作者：zx
    时间：2022.11.2
    描述：cpu自带的功能函数 
*/


#ifndef CPU_INSTR_H
#define CPU_INSTR_H
#include "types.h"

// 关中断
static inline void cli(void)
{
    __asm__ __volatile__("cli");
}

// 开中断
static inline void sti(void)
{
    __asm__ __volatile__("sti");
}

// 从端口拿去数据
static inline uint8_t inb(uint16_t port)
{
    uint8_t rv;
    // mov dx,port
    // inb al,dx
    // mov rv,al
    __asm__ __volatile__("inb %[p], %[v]" : [v]"=a" (rv) : [p]"d"(port));
    return rv;
}

// 放数据进入端口
static inline uint8_t outb(uint16_t port, uint8_t data)
{

    // mov dx,port 
    // out al,dx
    __asm__ __volatile__("outb %[v], %[p]" :: [p]"d"(port),[v]"a"(data));
}


// 加载gdt表
static inline void lgdt(uint32_t start, uint32_t size) {
	struct {
		uint16_t limit;
		uint16_t start15_0;    // 视频中这里写成了32位
		uint16_t start31_16;    // 视频中这里写成了32位
	} gdt;

	gdt.start31_16 = start >> 16;
	gdt.start15_0 = start & 0xFFFF;
	gdt.limit = size - 1;

	__asm__ __volatile__("lgdt %[g]"::[g]"m"(gdt));
}

// 加载idt表
static inline void lidt(uint32_t start, uint32_t size) {
	struct {
		uint16_t limit;
		uint16_t start15_0;    // 视频中这里写成了32位
		uint16_t start31_16;    // 视频中这里写成了32位
	} idt;

	idt.start31_16 = start >> 16;
	idt.start15_0 = start & 0xFFFF;
	idt.limit = size - 1;

    __asm__ __volatile__("lidt %[g]"::[g]"m"(idt));
}

// 读取cr0寄存器	
static inline uint32_t read_cr0(void)
{
    uint32_t cr0;
    __asm__ __volatile__("mov %%cr0, %[v]":[v]"=r"(cr0));
    return cr0;
}

// 写cr0 处理器
static inline void write_cr0(uint32_t cr0)
{
    __asm__ __volatile__("mov %[v], %%cr0"::[v]"r"(cr0));
}

// 读取cr2寄存器	
static inline uint32_t read_cr2(void)
{
    uint32_t cr2;
    __asm__ __volatile__("mov %%cr2, %[v]":[v]"=r"(cr2));
    return cr2;
}

// 写cr2 处理器
static inline void write_cr2(uint32_t cr2)
{
    __asm__ __volatile__("mov %[v], %%cr2"::[v]"r"(cr2));
}

// 读取cr3寄存器	
static inline uint32_t read_cr3(void)
{
    uint32_t cr3;
    __asm__ __volatile__("mov %%cr3, %[v]":[v]"=r"(cr3));
    return cr3;
}

// 写cr3 处理器
static inline void write_cr3(uint32_t cr3)
{
    __asm__ __volatile__("mov %[v], %%cr3"::[v]"r"(cr3));
}

// 读取cr4寄存器	
static inline uint32_t read_cr4(void)
{
    uint32_t cr4;
    __asm__ __volatile__("mov %%cr4, %[v]":[v]"=r"(cr4));
    return cr4;
}

// 写cr4 处理器
static inline void write_cr4(uint32_t cr4)
{
    __asm__ __volatile__("mov %[v], %%cr4"::[v]"r"(cr4));
} 


// 远调转
static inline void far_jump(uint32_t selector, uint32_t offset)
{
    uint32_t addr[] = {offset, selector};
    __asm__ __volatile__("ljmpl *(%[v])"::[v]"r"(addr));
}

// 从端口读取数据 一次两个字节
static inline uint16_t inw(uint16_t port)
{
    uint16_t rv;
    // mov dx,port
    // inb al,dx
    // mov rv,al
    __asm__ __volatile__("in %[p], %[v]" : [v]"=a" (rv) : [p]"d"(port));
    return rv;
}

// 写入端口数据 一次两个字节
static inline uint16_t outw(uint16_t port, uint16_t data)
{
    __asm__ __volatile__("out %[v], %[p]" :: [p]"d"(port),[v]"a"(data));
}


// 系统暂停
static inline void hlt(void)
{
    __asm__ __volatile__("hlt");
}

// 将gdt_tss_selector写入任务寄存器task register
static inline void write_tr(uint16_t gdt_selector)
{
    __asm__ __volatile__("ltr %%ax"::"a"(gdt_selector));
}

// 读取eflags寄存器
static inline uint32_t read_eflags(void)
{
    uint32_t eflags;
    // 不能直接获取eflags寄存器内容
    // pushf将寄存器入栈，pop出栈
    __asm__ __volatile__("pushf\n\tpop %%eax":"=a"(eflags));
    return eflags;
}

// 写eflags寄存器
static inline void write_eflags(uint32_t eflags) 
{
    __asm__ __volatile__("push %%eax\n\tpopf"::"a"(eflags));
}

#endif 